# -*- coding: utf-8 -*-
"""
@Author: Logan
@Date:   2025/7/7 14:08
@Description:
conftest.py 是 Python 测试框架（如 pytest）中的一个特殊文件，用于定义全局测试配置和共享资源。以下是其核心特性的简述：
1. 自动发现与作用域
自动发现：pytest 会自动识别项目中的 conftest.py 文件，无需手动导入。
分层作用域：
根目录的 conftest.py 影响所有测试。
子目录的 conftest.py 仅影响该目录及其子目录的测试。
2. 共享 Fixture 函数
Fixture 定义：通过 @pytest.fixture 装饰器定义可复用的 setup/teardown 逻辑。
自动执行：设置 autouse=True 可自动应用于所有测试。
参数化：支持为测试提供多组参数（如不同浏览器配置）。
┌─────────────────────────────────────────┐
│  钩子前置代码（yield 之前）              │
├─────────────────────────────────────────┤
│  ↓                                      │
│  pytest 执行测试用例                    │
│  ↑                                      │
├─────────────────────────────────────────┤
│  钩子后置代码（yield 之后，可访问结果）  │
└─────────────────────────────────────────┘
"""
import sys

import pytest
import subprocess
from common.ding_talk import send_dingtalk_msg, send_dingtalk_msg_markdown
from common.process_redis import Process
from common.report_add_img import add_img_2_report
from config.driver_config import DriverConfig
from config.yaml_config import GetConf


@pytest.fixture()
def driver():
    global get_driver
    get_driver = DriverConfig().driver_config()
    yield get_driver
    get_driver.quit()


@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_makereport(item, call):
    # 【前置执行】在测试用例执行前运行
    out = yield  # 暂停执行，等待测试用例执行完成
    # 【后置执行】在测试用例执行完成后运行,获取测试报告
    report = out.get_result()
    report.description = str(item.function.__doc__)  # 设置测试用例描述为函数文档字符串

    if report.when == "call":  # 仅处理测试用例的执行阶段（而非setup/teardown）
        if report.failed:  # 如果测试用例失败
            add_img_2_report(get_driver, "失败截图", need_sleep=False)  # 截取当前页面并添加到报告
            Process().update_fail()
            # 增加失败用例名称到表
            Process().insert_into_fail_testcase_names(report.description)
            # 获取当前进度
        elif report.passed:
            # 更新成功用例个数
            Process().update_success()
            # 获取当前进度
        else:
            pass
        process = Process().get_process()
        print(process)
        # 将测试进度发送到钉钉
        webhook = GetConf().get_dingding_webhook()
        send_dingtalk_msg(
            webhook,
            "测试用例: "
            + report.description
            + "\n测试结果: "
            + report.outcome
            + "\n自动化测试进度: "
            + process,
        )


# pytest_addoption 和 pytest_collection_modifyitems 都属于 pytest 官方钩子,可以不用声名
# 1. 添加自定义命令行参数
@pytest.hookimpl(tryfirst=True)  # 声明为钩子函数，tryfirst=True 表示优先执行
def pytest_addoption(parser):
    print("pytest_addoption 被调用")  # 调试打印
    parser.addoption("--count-tests", action="store_true", help="显示测试用例统计")


# 2. 在测试收集完成后执行统计
@pytest.hookimpl(tryfirst=True)  # 声明为钩子函数，tryfirst=True 表示优先执行
def pytest_collection_modifyitems(session, config, items):  # 仅适用单线程
    print("pytest_collection_modifyitems 被调用")  # 调试打印
    if config.getoption("--count-tests"):
        print(f"\n=== 发现 {len(items)} 个测试用例 ===")


def pytest_xdist_setupnodes(config, specs):
    if config.getoption("--count-tests"):
        print(f"\n=== 准备在 {len(specs)} 个工作节点上并行执行 ===")


def pytest_collection_finish(session):
    # 所有用例个数
    total = len(session.items)
    print(session.items)
    # 重置用例进度和失败用例名称
    Process().reset_all()
    # 初始化进度
    Process().init_process(total)

